package com.rtsapp.server.benchmark.runner;

import com.rtsapp.server.benchmark.ITestCaseConfig;
import com.rtsapp.server.benchmark.runner.channel.CommandCaseChannelInitializer;
import com.rtsapp.server.benchmark.runner.channel.CryptoCommandCaseChannelInitializer;
import com.rtsapp.server.network.protocol.crypto.client.ClientRSAHandshakeKey;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import com.rtsapp.server.logger.Logger;

import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;

/**
 *  单次测试连接
 */
public class TestConnection {

    private static final Logger LOGGER =com.rtsapp.server.logger.LoggerFactory.getLogger( TestConnection.class );

    /**
     * 所属的session
     */
    private final TestSession session;

    /**
     * 调度的eventLoop
     */
    private final EventLoopGroup eventLoop;

    /**
     * 针对的连接
     */
    private final SocketAddress remotePeer;

    /**
     * 针对的测试用例
     */
    private final ITestCaseConfig caseConfig;

    /**
     * 创建的
     */
    private final ChannelInitializer commandTestInitializer;


    public TestConnection(TestSession session, EventLoopGroup eventLoop, SocketAddress remotePeer, ITestCaseConfig caseConfig, ICommandCaseHandlerFactory commandCaseHandlerFactory, ClientRSAHandshakeKey keyRSA ) {
        this.session = session;
        this.eventLoop = eventLoop;
        this.remotePeer = remotePeer;
        this.caseConfig = caseConfig;

        if( keyRSA == null ) {
            this.commandTestInitializer = new CommandCaseChannelInitializer(commandCaseHandlerFactory, eventLoop, caseConfig.newTestCaseIterator(session.getContext()), session.getContext());
        }else{
            this.commandTestInitializer =  new CryptoCommandCaseChannelInitializer(commandCaseHandlerFactory, eventLoop, caseConfig.newTestCaseIterator(session.getContext()), session.getContext() , keyRSA );
        }
    }


    /**
     * 连接启动
     * @param delay
     */
    public void start( long delay  ){
        connect( delay );
    }

    /**
     * 连接
     * @param delay
     */
    private void connect( long delay ){
        this.eventLoop.schedule(  new ConnectTask( ), delay, TimeUnit.MILLISECONDS );
    }

    /**
     * 重连
     */
    private void reconnect( ){
        this.eventLoop.schedule(  new ConnectTask( ), 1000, TimeUnit.MILLISECONDS );
    }

    /**
     * 连接任务
     */
    private class ConnectTask implements Runnable{

        @Override
        public void run() {
            try {
                Bootstrap b = new Bootstrap();

                b.group( eventLoop )
                        .channel( NioSocketChannel.class )
                        .handler(commandTestInitializer);

                ChannelFuture channelFuture = b.connect(remotePeer);
                channelFuture.addListener(new ChannelFutureListener() {

                    @Override
                    public void operationComplete(final ChannelFuture channelFuture) throws Exception {

                        if (channelFuture.isSuccess()) {

                            // 设置连接关闭时，回调onConnectionClose
                            channelFuture.channel().closeFuture().addListener(future -> {
                                session.onConnectionClosed(TestConnection.this);
                            });


                            // 回调onConnectionStart
                            session.onConnectionConnected(TestConnection.this);

                        } else {
                            LOGGER.info("连接失败,将重连");
                            reconnect();
                        }
                    }
                });

            } catch (Exception e) {
                LOGGER.warn("连接异常", e);
                reconnect();
            }
        }

    }



}
